/*
 * © 2010 Autodata Solutions Company. All Rights Reserved
 * This source code is the confidential and proprietary information of Autodata Solutions Company.
 * The user shall not, in whole or in part, copy, publish, disclose or make any use of this source code
 * without the prior written consent of Autodata Solutions Company.
 */
Ext.ns('net.autodata.compare');

(function () {
	
	
	
	/**
	 * The class does not have a public constructor
	 * @class CompareVehiclesPanelStore
	 * @namespace net.autodata.compare.data
	 */
	var Store = Ext.extend(Ext.data.Store, {
		constructor: function (cfg)
		{
			this.addEvents({
				'updatecompetitor': true,
				'imageupdated': true
			});
			
			//Private helper functions
			function convertCode(o)
			{
				return o.code;
			}
			
			function convertDesc(o)
			{
				return o.description;
			}
			
			function convertIsCompetitor(o) 
			{
				return Ext.isEmpty(o);
			}
			
			function convertInvStockCount(o)
			{
				return o ? o.stockCount : -1;
			}
			
			function convertInvStartPrice(o)
			{
				return o ? o.startPrice : -1;
			}
			
			function convertInvEndPrice(o)
			{
				return o ? o.endPrice : -1;
			}
			
			function convertInvUrl(o)
			{
				return o ? o.url : '';
			}
			
			cfg = cfg || {};
			
			Ext.apply(cfg, {
				autoLoad: false,
				reader: new Ext.data.JsonReader({
					idProperty: 'acode',
					root: 'rows',
					
					fields: [
						{name: 'acode'},
						{name: 'isCompetitor', mapping: 'commonCompetitors', convert: convertIsCompetitor},
						{name: 'sponsored'},
						{name: 'modelYearCode', mapping: 'modelYear', convert: convertCode},
						{name: 'modelYear', mapping: 'modelYear', convert: convertDesc},
						{name: 'makeCode', mapping: 'make', convert: convertCode},
						{name: 'make', mapping: 'make', convert: convertDesc},
						{name: 'modelCode', mapping: 'model', convert: convertCode},
						{name: 'model', mapping: 'model', convert: convertDesc},
						{name: 'trimCode', mapping: 'trim', convert: convertCode},
						{name: 'trim', mapping: 'trim', convert: convertDesc},
						{name: 'imageName'},
						{name: 'selectedImageName'},
						{name: 'msrp', type: 'float'},
						{name: 'stockCount', mapping: 'inventory', convert: convertInvStockCount},
						{name: 'startPrice', mapping: 'inventory', convert: convertInvStartPrice},
						{name: 'endPrice', mapping: 'inventory', convert: convertInvEndPrice},
						{name: 'url', mapping: 'inventory', convert: convertInvUrl}
					]
				})
			});
			
			Store.superclass.constructor.call(this, cfg);
		},
		
		/**
		 * return the Base Vehicle record
		 * @method getBaseVehicle
		 */
		getBaseVehicle: function ()
		{
			var index = this.findExact('isCompetitor', false, 0);
			return index > -1 ? this.getAt(index) : undefined;
		},
		
		/**
		 * Calls the specified function for each of the {@link Ext.data.Record Records} in the cache.
		 * @method each
		 * @param {Function} fn The function to call. The {@link Ext.data.Record Record} is passed as the first parameter.
		 * Returning false aborts and exits the iteration.
		 * @param {Object} scope (optional) The scope (this reference) in which the function is executed.
		 * Defaults to the current {@link Ext.data.Record Record} in the iteration.
		 * @param {bool} all Flag to indicate if the base vehicle should be included
		 */
		each: function (fn, scope, all)
		{			
			var vehicleIdx = 0;
			this.data.each(function (record, index, length) {
				if (all !== true && !record.get('isCompetitor')) {
					return;
				}
				
				fn.call(scope, record, vehicleIdx++, length);
				
			}, this);
		},
		
		/**
		 * TODO Implement this method
		 * @method getCompetitorByIndex
		 */
		getCompetitorByIndex: function ()
		{
			///TODO determine way to lookup a competitor record based on it's index
			///perhaps the proxy can add the index
		},
		
		updateSelectedImage: function (acode, imageName)
		{
			var r = this.getById(acode);
			if (r) {
				r.data.selectedImageName = imageName;
				this.fireEvent('imageupdated', r);
			}
		},
		
		/**
		 * Update a competitor record within the store
		 * Fires updatecompetitor event
		 * @method updateCompetitor
		 * @param {int} index
		 * @param {Object} competitor
		 */
		updateCompetitor: function (index, competitor)
		{
			var competitorIndex = index + 1;
			
			competitor = competitor || {};
			Ext.applyIf(competitor, {
				acode: undefined
			});
			
			//if there is no acode create an empty record otherwise we need to use the 
			//reader to process the data
			
			var response = this.reader.readRecords({rows: [competitor]});
			var record;
			if (response.success) {
				record = response.records[0];
			} else {
				throw 'invalid competitor object';
			}
			
			if (record.phantom) {
				record.id = String.format('competitor-{0}', index);
			}
			
			this.removeAt(competitorIndex);
			this.insert(competitorIndex, [record]);
			this.fireEvent('updatecompetitor', index, record);
		}
	});
	
	/**
	 * The Panel renders the display of the selected vehicles for the compare
	 * @class CompareVehiclesPanel
	 * @extends Ext.BoxComponent
	 * @namespace net.autodata.compare
	 */
	var Panel = Ext.extend(Ext.BoxComponent, {
		
		autoEl: {
			tag: 'div',
			cls: 'compareVehicles-panel'
		},
		
		width: 788,
		height: 220,
		
		view: undefined,
		viewCfg: undefined,
		
		store: undefined,
		
		constructor: function (cfg)
		{
			cfg = cfg || {};
			
			var storeCfg = cfg.storeCfg;
			delete cfg.storeCfg;
			
			this.store = new Store(storeCfg);
			
			this.addEvents({
				'beforechangebasevehicle': true,
				'changebasevehicle': true,
				'beforechangecompetitor': true,
				'changecompetitor': true,
				'beforeremovecompetitor': true,
				'removecompetitor': true
			});
			
			Panel.superclass.constructor.apply(this, arguments);
		},
		
		initComponent: function ()
		{
			Panel.superclass.initComponent.apply(this, arguments);	
			
			var view = this.getView();
			view.init(this);
			
			/*view.on({
				'compareanother': this.onChangeBaseVehicle,
				'change': this.onChangeCompetitor,
				'remove': this.onRemoveCompetitor,
				scope: this
			});*/
			
			this.mon(view, {
				scope: this,
				'compareanother': this.onChangeBaseVehicle,
				'change': this.onChangeCompetitor,
				'remove': this.onRemoveCompetitor
			});
		},
		
		/**
		 * @method getStore
		 * @returns net.autodata.compare.data.CompareVehiclesPanelStore
		 */
		getStore: function ()
		{
			return this.store;
		},
		
		/**
		 * Retrieve a reference to the view used to render this panel
		 * @method getView
		 * @returns Object
		 */
		getView: function ()
		{
			if (!this.view) {
				this.view = new net.autodata.compare.CompareVehiclesView(this.viewCfg) 
			}
			return this.view;
		},
		
		/**
		 * @method onRender
		 * @private
		 */
		onRender: function ()
		{
			Panel.superclass.onRender.apply(this, arguments);
			
			var view = this.getView();
			view.render();
		},
		
		/**
		 * @method onChangeBaseVehicle
		 * @private
		 */
		onChangeBaseVehicle: function ()
		{
			if (!this.fireEvent('beforechangebasevehicle')) {
				return;
			}
			
			this.fireEvent('changebasevehicle');
		},
		
		
		/**
		 * @method onChangeCompetitor
		 * @param {int} index
		 * @param {String} acode
		 * @private
		 */
		onChangeCompetitor: function (index, acode)
		{
			if (!this.fireEvent('beforechangecompetitor', index, acode)) {
				return;
			}
			
			this.fireEvent('changecompetitor', index, acode);
		},
		
		/**
		 * @method onRemoveCompetitor
		 * @param {int} index
		 * @private
		 */
		onRemoveCompetitor: function (index)
		{
			if (!this.fireEvent('beforeremovecompetitor', index)) {
				return;
			}
			
			//Find the competitor record being removed and replace it with a new empty record
			var store = this.getStore();
			store.updateCompetitor(index, undefined, true);
			
			this.fireEvent('removecompetitor', index);
		},
		
		/**
		 * @method onDestroy
		 * @private
		 */
		onDestroy: function ()
		{	
			
			Panel.superclass.onDestroy.apply(this, arguments);
		}
		
	});
	
	net.autodata.compare.CompareVehiclesPanel = Panel;
	
})();